<template><div><h2 id="响应" tabindex="-1"><a class="header-anchor" href="#响应"><span>响应</span></a></h2>
<p>当一个应用在处理完一个 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/runtime-requests.md" target="_blank" rel="noopener noreferrer">请求</a> 后, 这个应用会生成一个 <code v-pre>yii\web\Response</code> 响应对象并把这个响应对象发送给终端用户，这个响应对象包含的信息有 HTTP 状态码，HTTP 头和主体内容等，从本质上说，Wwb 应用开发最终的目标就是根据不同的请求去构建这些响应对象。</p>
<p>在大多数实际应用情况下，你应该主要地去处理 <code v-pre>response</code> 这个 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-application-components.md" target="_blank" rel="noopener noreferrer">应用组件</a>，在默认情况下，它是一个继承自 <code v-pre>yii\web\Response</code> 的实例，然而，Yii 也允许你创建自己的响应对象并发送给终端用户，这方面在后续会阐述。</p>
<p>在本节，我们将会讲述如何组装和构建响应并把它发送给终端用户。</p>
<h2 id="http-状态码" tabindex="-1"><a class="header-anchor" href="#http-状态码"><span>HTTP 状态码</span></a></h2>
<p>构建响应要做的第一件事就是声明请求是否被成功处理，我们可通过设置 [[yii\web\Response::$statusCode]] 这个属性来做到这一点，该属性接受一个有效的 <a href="https://tools.ietf.org/html/rfc2616#section-10" target="_blank" rel="noopener noreferrer">HTTP 状态码</a>。例如，表明该请求已被成功处理，可以设置状态码为 200，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">response</span><span class="token operator">-></span><span class="token property">statusCode</span> <span class="token operator">=</span> <span class="token number">200</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>尽管如此，大多数情况下不需要明确设置状态码，因为 [[yii\web\Response::statusCode]] 状态码默认为 200，如果需要指定请求失败，可抛出对应的 HTTP 异常，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name class-name-fully-qualified"><span class="token punctuation">\</span>yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>NotFoundHttpException</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>当 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/runtime-handling-errors.md" target="_blank" rel="noopener noreferrer">错误处理器</a> 捕获到一个异常，会从异常中提取状态码并赋值到响应，对于上述的 <code v-pre>yii\web\NotFoundHttpException</code> 对应 HTTP 404 状态码，以下为 Yii 预定义的 HTTP 异常：</p>
<ul>
<li><code v-pre>yii\web\BadRequestHttpException</code>：状态码 400，“Bad Request”</li>
<li><code v-pre>yii\web\UnauthorizedHttpException</code>：状态码 401，“Unauthorized”</li>
<li><code v-pre>yii\web\ForbiddenHttpException</code>：状态码 403，“Forbidden”</li>
<li><code v-pre>yii\web\NotFoundHttpException</code>：状态码 404，“Not Found”</li>
<li><code v-pre>yii\web\MethodNotAllowedHttpException</code>：状态码 405，“Method Not Allowed”</li>
<li><code v-pre>yii\web\NotAcceptableHttpException</code>：状态码 406，“Not Acceptable”</li>
<li><code v-pre>yii\web\ConflictHttpException</code>：状态码 409，“Conflict”</li>
<li><code v-pre>yii\web\GoneHttpException</code>：状态码 410，“Gone”</li>
<li><code v-pre>yii\web\UnsupportedMediaTypeHttpException</code>：状态码 415，“Unsupported Media Type”</li>
<li><code v-pre>yii\web\RangeNotSatisfiableHttpException</code>：状态码 416，“Requested range unsatisfiable”</li>
<li><code v-pre>yii\web\UnprocessableEntityHttpException</code>：状态码 422，“Unprocessable Entity”</li>
<li><code v-pre>yii\web\TooManyRequestsHttpException</code>：状态码 429，“Too Many Requests”</li>
<li><code v-pre>yii\web\ServerErrorHttpException</code>：状态码 500，“Internal Server Error”</li>
</ul>
<p>如果想抛出的异常不在如上列表中，可创建一个 <code v-pre>yii\web\HttpException</code> 异常，带上状态码抛出，如下：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name class-name-fully-qualified"><span class="token punctuation">\</span>yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>HttpException</span><span class="token punctuation">(</span><span class="token number">402</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h2 id="设置-http-响应头" tabindex="-1"><a class="header-anchor" href="#设置-http-响应头"><span>设置 HTTP 响应头</span></a></h2>
<p>可在 <code v-pre>response</code> 组件中操控 [[yii\web\Response::headers]] 来发送 HTTP 头部信息，例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$headers</span> <span class="token operator">=</span> <span class="token class-name static-context">Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">response</span><span class="token operator">-></span><span class="token property">headers</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 增加一个 Pragma 头，已存在的Pragma 头不会被覆盖。</span></span>
<span class="line"><span class="token variable">$headers</span><span class="token operator">-></span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Pragma'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'no-cache'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 设置一个Pragma 头. 任何已存在的Pragma 头都会被丢弃</span></span>
<span class="line"><span class="token variable">$headers</span><span class="token operator">-></span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Pragma'</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'no-cache'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token comment">// 删除Pragma 头并返回删除的Pragma 头的值到数组</span></span>
<span class="line"><span class="token variable">$values</span> <span class="token operator">=</span> <span class="token variable">$headers</span><span class="token operator">-></span><span class="token function">remove</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Pragma'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>Info: 头名称是大小写敏感的，在 [[yii\web\Response::send()]] 方法，调用前新注册的头信息并不会发送给用户。</p>
</blockquote>
<h2 id="响应主体" tabindex="-1"><a class="header-anchor" href="#响应主体"><span>响应主体</span></a></h2>
<p>大多是响应应有一个主体存放你想要显示给终端用户的内容。</p>
<p>如果已有格式化好的主体字符串，可赋值到响应的 [[yii\web\Response::content]] 属性，例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name static-context">Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">response</span><span class="token operator">-></span><span class="token property">content</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'hello world!'</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果在发送给终端用户之前需要格式化，应设置 [[yii\web\Response::format]] 和 [[yii\web\Response::data]] 属性，[[yii\web\Response::format]] 属性指定 [[yii\web\Response::data]]中数据格式化后的样式，例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$response</span> <span class="token operator">=</span> <span class="token class-name static-context">Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">response</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$response</span><span class="token operator">-></span><span class="token property">format</span> <span class="token operator">=</span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>Response</span><span class="token operator">::</span><span class="token constant">FORMAT_JSON</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token variable">$response</span><span class="token operator">-></span><span class="token property">data</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'message'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'hello world'</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Yii支持以下可直接使用的格式，每个实现了 <code v-pre>yii\web\ResponseFormatterInterface</code> 类，可自定义这些格式器或通过配置 [[yii\web\Response::formatters]] 属性来增加格式器。</p>
<ul>
<li>[[yii\web\Response::FORMAT_HTML]]：通过 [[yii\web\HtmlResponseFormatter]] 来实现。</li>
<li>[[yii\web\Response::FORMAT_XML]]：通过 [[yii\web\XmlResponseFormatter]] 来实现。</li>
<li>[[yii\web\Response::FORMAT_JSON]]：通过 [[yii\web\JsonResponseFormatter]] 来实现。</li>
<li>[[yii\web\Response::FORMAT_JSONP]]：通过 [[yii\web\JsonResponseFormatter]] 来实现。</li>
<li>[[yii\web\Response::FORMAT_RAW]]：如果要直接发送响应而不应用任何格式，请使用此格式。</li>
</ul>
<p>上述响应主体可明确地被设置，但是在大多数情况下是通过 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/structure-controllers.md" target="_blank" rel="noopener noreferrer">动作</a> 方法的返回值隐式地设置，常用场景如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">actionIndex</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">render</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'index'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>上述的 <code v-pre>index</code> 操作返回 <code v-pre>index</code> 视图渲染结果，返回值会被 <code v-pre>response</code> 组件格式化后发送给终端用户。</p>
<p>因为响应格式默认为 [[yii\web\Response::FORMAT_HTML]]，只需要在操作方法中返回一个字符串，如果想使用其他响应格式，应在返回数据前先设置格式，例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">actionInfo</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">response</span><span class="token operator">-></span><span class="token property">format</span> <span class="token operator">=</span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>Response</span><span class="token operator">::</span><span class="token constant">FORMAT_JSON</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'message'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'hello world'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'code'</span> <span class="token operator">=></span> <span class="token number">100</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如上所述，除了使用默认的 <code v-pre>response</code> 应用组件，也可创建自己的响应对象并发送给终端用户， 可在操作方法中返回该响应对象，如下所示：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">actionInfo</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Yii</span><span class="token operator">::</span><span class="token function">createObject</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'class'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'yii\web\Response'</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'format'</span> <span class="token operator">=></span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>yii<span class="token punctuation">\</span>web<span class="token punctuation">\</span>Response</span><span class="token operator">::</span><span class="token constant">FORMAT_JSON</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token string single-quoted-string">'data'</span> <span class="token operator">=></span> <span class="token punctuation">[</span></span>
<span class="line">            <span class="token string single-quoted-string">'message'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'hello world'</span><span class="token punctuation">,</span></span>
<span class="line">            <span class="token string single-quoted-string">'code'</span> <span class="token operator">=></span> <span class="token number">100</span><span class="token punctuation">,</span></span>
<span class="line">        <span class="token punctuation">]</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>Note: 如果创建你自己的响应对象，将不能在应用配置中设置 <code v-pre>response</code> 组件，尽管如此，可使用 <a href="https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/concept-di-container.md" target="_blank" rel="noopener noreferrer">依赖注入</a> 应用通用配置到你新的响应对象。</p>
</blockquote>
<h2 id="浏览器跳转" tabindex="-1"><a class="header-anchor" href="#浏览器跳转"><span>浏览器跳转</span></a></h2>
<p>浏览器跳转依赖于发送一个 <code v-pre>Location</code> HTTP 头，因为该功能通常被使用，Yii 提供对它提供了特别的支持。</p>
<p>可调用 [[yii\web\Response::redirect()]] 方法将用户浏览器跳转到一个 URL 地址，该方法设置合适的 带指定 URL 的 <code v-pre>Location</code> 头并返回它自己为响应对象，在操作的方法中，可调用缩写版 [[yii\web\Controller::redirect()]]，例如：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">actionOld</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">redirect</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://example.com/new'</span><span class="token punctuation">,</span> <span class="token number">301</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在如上代码中，操作的方法返回 <code v-pre>redirect()</code> 方法的结果，如前所述，操作的方法返回的响应对象会被当总响应发送给终端用户。</p>
<p>除了动作方法外，可直接调用 [[yii\web\Response::redirect()]] 再调用 [[yii\web\Response::send()]] 方法来确保没有其他内容追加到响应中。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">response</span><span class="token operator">-></span><span class="token function">redirect</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'http://example.com/new'</span><span class="token punctuation">,</span> <span class="token number">301</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p>Info: [[yii\web\Response::redirect()]] 方法默认会设置响应状态码为 302，该状态码会告诉浏览器请求的资源 <em>临时</em> 放在另一个 URI 地址上，可传递一个 301 状态码告知浏览器请求 的资源已经 <em>永久</em> 重定向到新的 URI 地址。</p>
</blockquote>
<p>如果当前请求为 AJAX 请求，发送一个 <code v-pre>Location</code> 头不会自动使浏览器跳转，为解决这个问题， [[yii\web\Response::redirect()]] 方法设置一个值为要跳转的URL的 <code v-pre>X-Redirect</code> 头，在客户端可编写 JS 代码读取该头部值然后让浏览器跳转对应的 URL。</p>
<blockquote>
<p>Info: Yii 配备了一个 <code v-pre>yii.js</code> JS 文件提供常用 JS 功能，包括基于 <code v-pre>X-Redirect</code> 头的浏览器跳转，因此，如果你使用该 JS 文件（通过 <code v-pre>yii\web\YiiAsset</code> 资源包注册），就不需要编写 AJAX 跳转的代码。</p>
</blockquote>
<h2 id="发送文件" tabindex="-1"><a class="header-anchor" href="#发送文件"><span>发送文件</span></a></h2>
<p>和浏览器跳转类似，文件发送是另一个依赖指定 HTTP 头的功能，Yii 提供方法集合来支持各种文件发送需求，它们对 HTTP 头都有内置的支持。</p>
<ul>
<li>[[yii\web\Response::sendFile()]]：发送一个已存在的文件到客户端</li>
<li>[[yii\web\Response::sendContentAsFile()]]：发送一个文本字符串作为文件到客户端</li>
<li>[[yii\web\Response::sendStreamAsFile()]]：发送一个已存在的文件流作为文件到客户端</li>
</ul>
<p>这些方法都将响应对象作为返回值，如果要发送的文件非常大，应考虑使用 [[yii\web\Response::sendStreamAsFile()]] 因为它更节约内存，以下示例显示在控制器操作中如何发送文件：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">actionDownload</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">response</span><span class="token operator">-></span><span class="token function">sendFile</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'path/to/file.txt'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果不是在操作方法中调用文件发送方法，在后面还应调用 [[yii\web\Response::send()]] 没有其他内容追加到响应中。</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Yii</span><span class="token operator">::</span><span class="token variable">$app</span><span class="token operator">-></span><span class="token property">response</span><span class="token operator">-></span><span class="token function">sendFile</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'path/to/file.txt'</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>一些浏览器提供特殊的名为 <em>X-Sendfile</em> 的文件发送功能，原理为将请求跳转到服务器上的文件， Web 应用可在服务器发送文件前结束，为使用该功能，可调用 [[yii\web\Response::xSendFile()]]，如下简要列出一些常用 Web 服务器如何启用 <code v-pre>X-Sendfile</code> 功能：</p>
<ul>
<li>Apache: <a href="http://tn123.org/mod_xsendfile" target="_blank" rel="noopener noreferrer">X-Sendfile</a></li>
<li>Lighttpd v1.4: <a href="http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file" target="_blank" rel="noopener noreferrer">X-LIGHTTPD-send-file</a></li>
<li>Lighttpd v1.5: <a href="http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file" target="_blank" rel="noopener noreferrer">X-Sendfile</a></li>
<li>Nginx: <a href="https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/" target="_blank" rel="noopener noreferrer">X-Accel-Redirect</a></li>
<li>Cherokee: <a href="http://www.cherokee-project.com/doc/other_goodies.html#x-sendfile" target="_blank" rel="noopener noreferrer">X-Sendfile and X-Accel-Redirect</a></li>
</ul>
<h2 id="发送响应" tabindex="-1"><a class="header-anchor" href="#发送响应"><span>发送响应</span></a></h2>
<p>在 [[yii\web\Response::send()]] 方法调用前响应中的内容不会发送给用户，该方法默认在 [[yii\base\Application::run()]] 结尾自动调用，尽管如此，可以明确调用该方法强制立即发送响应。</p>
<p>[[yii\web\Response::send()]] 方法使用以下步骤来发送响应：</p>
<ol>
<li>触发 [[yii\web\Response::EVENT_BEFORE_SEND]] 事件。</li>
<li>调用 [[yii\web\Response::prepare()]] 来格式化 [[yii\web\Response::data]] 为 [[yii\web\Response::content]]。</li>
<li>触发 [[yii\web\Response::EVENT_AFTER_PREPARE]] 事件。</li>
<li>调用 [[yii\web\Response::sendHeaders()]] 来发送注册的HTTP头</li>
<li>调用 [[yii\web\Response::sendContent()]] 来发送响应主体内容</li>
<li>触发 [[yii\web\Response::EVENT_AFTER_SEND]] 事件。</li>
</ol>
<p>一旦 [[yii\web\Response::send()]] 方法被执行后，其他地方调用该方法会被忽略， 这意味着一旦响应发出后，就不能再追加其他内容。</p>
<p>如你所见 [[yii\web\Response::send()]] 触发了几个实用的事件， 通过响应这些事件可调整或包装响应。</p>
<blockquote>
<p>💖喜欢本文档的，欢迎点赞、收藏、留言或转发，谢谢支持！<br>
作者邮箱：zhuzixian520@126.com，github地址：<a href="https://github.com/zhuzixian520" target="_blank" rel="noopener noreferrer">github.com/zhuzixian520</a></p>
</blockquote>
</div></template>


